﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace NGIS.Data.Schema
{
    public class UdxNodeSchema
    {
        protected string mName;
        protected UdxNodeDescription mDescription;
        protected List<UdxNodeSchema> mChildNodes;
        protected UdxNodeSchema mParentNode;
        protected int mExtension;

        public UdxNodeSchema(UdxNodeSchema pParent, string pName, UdxNodeDescription pDescription)
        {
            mName = pName;
            mParentNode = pParent;
            mDescription = pDescription;
            mChildNodes = new List<UdxNodeSchema>();
        }

        public string getName()
        {
            return mName;
        }

        public UdxNodeDescription getDescription()
        {
            return mDescription;
        }

        public bool modifyName(string pName)
        {
            string pNameStr = pName;
            if (mName == pNameStr) return false;
            mName = pName;
            return true;
        }

        public UdxNodeSchema getParentNode()
        {
            return mParentNode;
        }

        public int getChildNodeCount()
        {
            return mChildNodes.Count;
        }

        public UdxNodeSchema getChildNode(int idx)
        {
            if (idx < 0 || idx >= mChildNodes.Count) return null;
            return mChildNodes[idx];
        }

        public UdxNodeSchema addChildNode(string pName, UdxNodeDescription pDescription)
        {
            ESchemaNodeType mType = mDescription.getKernelType();
            if (mType == ESchemaNodeType.EDTKT_INT ||
                mType == ESchemaNodeType.EDTKT_REAL ||
                mType == ESchemaNodeType.EDTKT_STRING ||
                mType == ESchemaNodeType.EDTKT_VECTOR2 ||
                mType == ESchemaNodeType.EDTKT_VECTOR3 ||
                mType == ESchemaNodeType.EDTKT_VECTOR4 ||
                mType == (ESchemaNodeType.EDTKT_INT | ESchemaNodeType.EDTKT_LIST) ||
                mType == (ESchemaNodeType.EDTKT_REAL | ESchemaNodeType.EDTKT_LIST) ||
                mType == (ESchemaNodeType.EDTKT_STRING | ESchemaNodeType.EDTKT_LIST) ||
                mType == (ESchemaNodeType.EDTKT_VECTOR2 | ESchemaNodeType.EDTKT_LIST) ||
                mType == (ESchemaNodeType.EDTKT_VECTOR3 | ESchemaNodeType.EDTKT_LIST) ||
                mType == (ESchemaNodeType.EDTKT_VECTOR4 | ESchemaNodeType.EDTKT_LIST))
            {
                return null;
            }
            else if (mType == ESchemaNodeType.EDTKT_LIST)
            {
                if (mChildNodes.Count >= 1)
                    return null;
            }
            else if (mType == ESchemaNodeType.EDTKT_MAP)
            {
                if (mChildNodes.Count >= 2)
                    return null;
            }
            else if (mType == ESchemaNodeType.EDTKT_TABLE)
            {
                bool isOK = false;
                ESchemaNodeType pType = pDescription.getKernelType();
                if (pType == (ESchemaNodeType.EDTKT_INT | ESchemaNodeType.EDTKT_LIST) ||
                    pType == (ESchemaNodeType.EDTKT_REAL | ESchemaNodeType.EDTKT_LIST) ||
                    pType == (ESchemaNodeType.EDTKT_STRING | ESchemaNodeType.EDTKT_LIST) ||
                    pType == (ESchemaNodeType.EDTKT_VECTOR2 | ESchemaNodeType.EDTKT_LIST) ||
                    pType == (ESchemaNodeType.EDTKT_VECTOR3 | ESchemaNodeType.EDTKT_LIST) ||
                    pType == (ESchemaNodeType.EDTKT_VECTOR4 | ESchemaNodeType.EDTKT_LIST))
                {
                    isOK = true;
                }
                if (isOK == false) return null;
            }
            UdxNodeSchema pNode = new UdxNodeSchema(this, pName, pDescription);
            mChildNodes.Add(pNode);
            return pNode;
        }

        public UdxNodeSchema addChildNode(string pName, ESchemaNodeType pNodeType, string pNodeInfo = "")
        {
            UdxNodeDescription pDescription = new UdxNodeDescription(pNodeType, pNodeInfo);
            UdxNodeSchema pNode = addChildNode(pName, pDescription);
            return pNode;
        }

        public bool removeChildNode(UdxNodeSchema pNode)
        {
            for (int i = 0; i < mChildNodes.Count; i++)
            {
                if (mChildNodes[i] == pNode)
                {
                    mChildNodes.RemoveAt(i);
                    return true;
                }
            }
            return false;
        }

        public bool removeChildNode(int idx)
        {
            if (idx >= 0 && idx < mChildNodes.Count)
            {
                mChildNodes.RemoveAt(idx);
                return true;
            }
            return false;
        }

        public void setExtension(int flag)
        {
            mExtension = flag;
        }

        public int getExtension()
        {
            return mExtension;
        }

        public bool compareOther(UdxNodeSchema pNode)
        {
            if (compareNodeInfo(this, pNode) == false)
            {
                return false;
            }
            for (int iChild = 0; iChild < pNode.getChildNodeCount(); iChild++)
            {
                UdxNodeSchema tempNode1 = this.getChildNode(iChild);
                UdxNodeSchema tempNode2 = pNode.getChildNode(iChild);

                if (tempNode1.compareOther(tempNode2) == false)
                {
                    return false;
                }
            }
            return true;
        }

        private bool compareNodeInfo(UdxNodeSchema pNode1, UdxNodeSchema pNode2)
        {
            int count1 = pNode1.getChildNodeCount();
            int count2 = pNode2.getChildNodeCount();
            if (count1 != count2)
            {
                return false;
            }
            if (pNode1.getDescription().getKernelType() != pNode2.getDescription().getKernelType())
            {
                return false;
            }
            string name1 = pNode1.getName();
            string name2 = pNode2.getName();
            if (name1 != name2)
            {
                return false;
            }
            string desc1 = pNode1.getDescription().getNodeDescription();
            string desc2 = pNode2.getDescription().getNodeDescription();
            if (desc1 != desc2)
            {
                return false;
            }
            string tag1 = pNode1.getDescription().getConceptTag();
            string tag2 = pNode2.getDescription().getConceptTag();
            if (tag1 != tag2)
            {
                return false;
            }
            tag1 = pNode1.getDescription().getSpatialReferencefTag();
            tag2 = pNode2.getDescription().getSpatialReferencefTag();
            if (tag1 != tag2)
            {
                return false;
            }
            tag1 = pNode1.getDescription().getUnitTag();
            tag2 = pNode2.getDescription().getUnitTag();
            if (tag1 != tag2)
            {
                return false;
            }
            tag1 = pNode1.getDescription().getDimensionTag();
            tag2 = pNode2.getDescription().getDimensionTag();
            if (tag1 != tag2)
            {
                return false;
            }
            tag1 = pNode1.getDescription().getDataTemplateTag();
            tag2 = pNode2.getDescription().getDataTemplateTag();
            if (tag1 != tag2)
            {
                return false;
            }
            return true;
        }

    };
}
